package security.Checkpoint;

import security.Session.*;
import security.Roles.*;
import security.SingleAccessPoint.*;
import java.util.Vector;
import security.*;

/**
 * Singleton Checkpoint class which the controller of the security implementation
 */
public class Checkpoint {
	
	
	/* BEGIN Static */
	private static Checkpoint checkpoint;
	
	private SecurityPolicy sp;
	
	private Checkpoint() {
		
		// generate testdata
		VectorInitClass test = new VectorInitClass();
		
		// create security policy
		sp = new ConcreteSecurityPolicy();

		// loading user data
		users.addAll(VectorUser.getUsers());
	}
	
	public static Checkpoint getCheckpoint() {
		if (checkpoint == null) {
			checkpoint = new Checkpoint();
		}
		return checkpoint;
	}
	/* END Static */
	
	private Vector<Session> sessions = new Vector<Session>();
	private Vector<User> users = new Vector<User>();				// users object
	
	
	/**
	 * @param identifier - string defining the package.class.method that should be called
	 * @param ap - accesspoint who sent the request
	 * @param sessionId
	 * @return
	 */
	public boolean checkMe(Object[] identifier, SingleAccessPoint ap, String sessionId) {
		// need to be logged in
		if (! isLoggedIn(sessionId)) {
			int i = 0;
			while (! login(ap.getAuthentication("You need to be logged in to perform this action:"), sessionId)) {				
				if (i == 2) {
					ap.returnMessage("Cannot log you in.");
					return false;					
				}
				i++;
			}
			return true;
		}
		
		// check the security policy
		if (! sp.isAllowed(identifier)) {
			ap.returnMessage("Security policy violated.");
			return false;
		}	
		
		// check the privileges
		
		for(int i=0;i<getSession(sessionId).getCurrentUser().getUserPrivilege().size();i++) {
			if (! getSession(sessionId).getCurrentUser().getUserPrivilege().get(i).isAllowed(identifier)) {
				ap.returnMessage("Privileges violated.");
				return false;
			}
		}		
	
		
		return true;
	}

	public boolean login(AuthenticationToken token, String sessionId) {		
		for (int i=0;i<users.size();i++){
			//System.out.println(users.get(i).getUserName());
			if (users.get(i).getUserName().equals(token.getUsername())) {				
				if (users.get(i).getUserToken().encrypted().equals(token.encrypted())) {
					this.getSession(sessionId).setCurrentUser(users.get(i));
					this.getSession(sessionId).setLoggedIn(true);					
					return true;
				}
			}
		}
		return false;
	}
	
	public boolean isLoggedIn(String sessionId) {
		return getSession(sessionId).isLoggedIn(); 
	}
	
	public String getSessionId(String sessionId) {
		return getSession(sessionId).getSessionId();
	}
	
	/**
	 * return same if session exists, else create and add to sessions
	 * @param sessionId sessionId == null --> create new Session
	 * @param sessionId	sessionId != null -> if session exists -> return sessionId
  	 * @param sessionId sessionId != null -> session does not exist (faulty sessionId) -> return NEW sessionId
	 * @return sessionId, either new or same see ^
	 */
	public Session getSession(String sessionId) {
		if (sessionId == null || sessionId == "") {
			// create new session
			Session newSession = new Session();
			this.sessions.add(newSession);
			return newSession;
		} else {
			// check if sessionId exists
			for (int i=0;i<sessions.size();i++){
				if (sessions.get(i).getSessionId().equals(sessionId)) {
					return sessions.get(i);
				}
			}
		}
		// create new session / session does not exist
		Session newSession = new Session();
		this.sessions.add(newSession);
		return newSession;		
	}
	
}
